using System;
using System.Collections.Generic;


namespace NMockExtensions
{
    public class Event
    {
        public static void Fire(string eventName, object mockSource, object args)
        {
            Remember.mocksWithEvents.FireEvent(mockSource, eventName, args);
        }
    }

    internal class ListOfHandlers : List<Delegate>
    {
    }

    internal class ListOfEvents : Dictionary<string, ListOfHandlers>
    {
    }

    internal class ListOfMocksWithEvents : Dictionary<object, ListOfEvents>
    {
        public void AddHandler(object mock, string eventName, Delegate handler)
        {
            GetHandlers(eventName, mock).Add(handler);
        }

        private ListOfHandlers GetHandlers(string eventName, object mock)
        {
            EnsureListOfHandlers(eventName, mock);
            return this[mock][eventName];
        }

        private void EnsureListOfHandlers(string eventName, object mock)
        {
            if (!ContainsKey(mock)) this[mock] = new ListOfEvents();
            if (!this[mock].ContainsKey(eventName)) this[mock][eventName] = new ListOfHandlers();
        }

        public void RemoveHandler(object mock, string eventName, Delegate handler)
        {
            if (ContainsKey(mock) && this[mock].ContainsKey(eventName))
                this[mock][eventName].Remove(handler);
        }

        public void FireEvent(object mock, string eventName, object eventargs)
        {
            ListOfHandlers handlers = GetHandlers(eventName, mock);
            foreach (Delegate handler in handlers)
            {
                handler.Method.Invoke(handler.Target, new object[] {mock, eventargs});
            }
        }
    }
}